/**
 * Copyright (c) 2005-2016, yinwer81 (yinwer81@aliyun.com)
 *
 * Licensed under the Apache License, Version 2.0
 */
package com.nozturn.throne.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.stereotype.Repository;

import com.nozturn.throne.dao.ClientDao;
import com.nozturn.throne.entity.Client;

@Repository
public class ClientDaoImpl implements ClientDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public Client createClient(final Client client) {
        final String sql = "insert into tbl_client(client_name, client_id, client_secret, client_owner, redirect_uri, valid, created_at, updated_at, created_by, updated_by) values(?,?,?,?,?,?,now(),now(),?,?)";

        final GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(new PreparedStatementCreator() {

            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                PreparedStatement psst = connection.prepareStatement(sql, new String[] { "pk" });
                int count = 1;
                psst.setString(count++, client.getClientName());
                psst.setString(count++, client.getClientId());
                psst.setString(count++, client.getClientSecret());
                psst.setLong(count++, client.getClientOwner());
                psst.setString(count++, client.getRedirectUri());
                psst.setInt(count++, client.getValid());
                psst.setString(count++, client.getCreatedBy());
                psst.setString(count++, client.getUpdatedBy());
                return psst;
            }
        }, keyHolder);

        client.setPk(keyHolder.getKey().longValue());
        return client;
    }

    public int updateClient(final Client client) {
        final String sql = "update tbl_client set client_name=?, client_id=?, client_secret=?, client_owner=?, redirect_uri=?, valid=?, updated_at=now(), updated_by=? where valid=200 and pk=?";
        int updated = jdbcTemplate.update(sql, client.getClientName(), client.getClientId(), client.getClientSecret(), client.getClientOwner(),
                client.getRedirectUri(), client.getValid(), client.getUpdatedBy(), client.getPk());
        return updated;
    }

    public int deleteClient(final Long pk) {
        final String sql = "update tbl_client set valid=100, updated_at=now(), updated_by='system' where valid=200 and pk=?";
        int deleted = jdbcTemplate.update(sql, pk);
        return deleted;
    }

    public Client findOne(final Long pk) {
        final String sql = "select pk, client_name, client_id, client_secret, valid, created_at, updated_at, created_by, updated_by from tbl_client where valid=200 and pk=?";
        final List<Client> clientList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Client>(Client.class), pk);
        if (clientList.size() == 0) {
            return null;
        }
        return clientList.get(0);
    }

    public List<Client> findAll() {
        final String sql = "select pk, client_name, client_id, client_secret, client_owner, redirect_uri, valid, created_at, updated_at, created_by, updated_by from tbl_client where valid=200";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Client>(Client.class));
    }

    public Client findByClientId(final String clientId) {
        final String sql = "select pk, client_name, client_id, client_secret, client_owner, redirect_uri, valid, created_at, updated_at, created_by, updated_by from tbl_client where valid=200 and client_id=?";
        final List<Client> clientList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Client>(Client.class), clientId);
        if (clientList.size() == 0) {
            return null;
        }
        return clientList.get(0);
    }

    public Client findByClientSecret(final String clientSecret) {
        final String sql = "select pk, client_name, client_id, client_secret, client_owner, redirect_uri, valid, created_at, updated_at, created_by, updated_by from tbl_client where valid=200 and client_secret=?";
        final List<Client> clientList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Client>(Client.class), clientSecret);
        if (clientList.size() == 0) {
            return null;
        }
        return clientList.get(0);
    }

    public List<Client> findByClient(final Client client) {
        final String sql = "select pk, client_name, client_id, client_secret, client_owner, redirect_uri, valid, created_at, updated_at, created_by, updated_by from tbl_client where valid=200 and (? is null or pk = ?) and (client_id is null or client_id = ?)";
        final List<Client> clientList = new ArrayList<Client>();
        jdbcTemplate.query(sql, new Object[] { client.getPk(), client.getPk(), client.getClientId(), client.getClientId() },
                new RowCallbackHandler() {
                    public void processRow(ResultSet rs) throws SQLException {
                        Client client = new Client();
                        client.setPk(rs.getLong("pk"));
                        client.setClientName(rs.getString("client_name"));
                        client.setClientId(rs.getString("client_id"));
                        client.setClientSecret(rs.getString("client_secret"));
                        client.setClientOwner(rs.getLong("client_owner"));
                        client.setRedirectUri(rs.getString("redirect_uri"));
                        client.setValid(rs.getInt("valid"));
                        client.setCreatedAt(rs.getDate("created_at"));
                        client.setCreatedBy(rs.getString("created_by"));
                        client.setUpdatedAt(rs.getDate("updated_at"));
                        client.setUpdatedBy(rs.getString("updated_by"));
                        clientList.add(client);
                    }
                });
        return clientList;
    }
}
